#ifndef _PART2D_EDITOR_H_
#define _PART2D_EDITOR_H_

#include "gameflow/ui_state.h"
#include "math/vec4.h"
#include "math/counter.h"
#include "ui/ui_widget.h"

namespace LuaPlus
{
	class LuaState;
}

namespace part2d
{

class Part2D;
class P2DEdit;

class P2DEdit_Container
{
public:
	enum CONTAINER_CMD {
		CMD_LOAD = 0,
		CMD_SAVE,
		CMD_IMAGE,
		CMD_GROUP,
		CMD_ADDGROUP,
		CMD_DELGROUP,
		CMD_MAXC,
		CMD_ADDITIVE,
		CMD_LOCKRECT,
		CMD_FUZZYBIRTH,
		CMD_SIZEFROM_MIN,
		CMD_SIZEFROM_MAX,
		CMD_SIZETO_MIN,
		CMD_SIZETO_MAX,
		CMD_LIFESPAN,
		CMD_MINSPEED,
		CMD_MAXSPEED,
		CMD_STRETCHSPEED,
		CMD_MINSPEEDMAG,
		CMD_GENRATE,
		CMD_ADDCOLOR,
		CMD_CLEARCOLOR,
		CMD_GROUPCOUNT,

		CMD_CUSTOM = 1024,
	};

	union CONTAINER_VAL {
		unsigned long	dwData;
		int				iData;
		float			fData;
	};

	P2DEdit_Container(P2DEdit* pEditor);
	virtual ~P2DEdit_Container();

	// overrride for custom behavior
	virtual void		CreateParticle();

	virtual void		Setup(const math::Vec2& pos, const math::Vec2& size = math::Vec2());
	virtual bool		Tick(float dt);
	virtual void		Render(const math::Vec2& Min = math::Vec2(0.0f, 0.0f), const math::Vec2& Max = math::Vec2(1.0f, 1.0f));

	virtual int			SetCmd(const CONTAINER_CMD& cmd, const std::string& szData);
	virtual int			SetCmd(const CONTAINER_CMD& cmd, CONTAINER_VAL Data);
	virtual int			SetCmd(const CONTAINER_CMD& cmd, const math::Vec2& vData);
	virtual int			SetCmd(const CONTAINER_CMD& cmd, const math::Vec4& vData);
	int					SetCmd(const CONTAINER_CMD& cmd);
	int					SetCmd(const CONTAINER_CMD& cmd, int iData);
	int					SetCmd(const CONTAINER_CMD& cmd, float fData);
	int					SetCmd(const CONTAINER_CMD& cmd, unsigned long dwData);
	int					SetCmd(const CONTAINER_CMD& cmd, bool bData);

	bool				GetCmd(const CONTAINER_CMD& cmd, CONTAINER_VAL& val);
	bool				GetCmd(const CONTAINER_CMD& cmd, std::string& val);
	bool				GetCmd(const CONTAINER_CMD& cmd, math::Vec2& val);

	std::string&		GetFileName() { return m_FileName; }
	const math::Vec2&	GetPos() { return m_Pos; }
	const math::Vec2&	GetSize() { return m_Size; }
	int&				GetTriggerC() { return m_TriggerC; }
	math::Vec2&			GetOffset() { return m_Offset; }

protected:
	P2DEdit*			m_pEditor;
	Part2D*				m_pParticle;
	math::Vec2			m_Pos;
	math::Vec2			m_Offset;
	math::Vec2			m_Size;
	int					m_Current;
	int					m_TriggerC;
	math::Counter		m_TriggerCounter;

private:
	std::string			m_FileName;
};

class P2DEdit : public gameflow::UIState
{
public:
	enum PREVIEW_MODE {
		PREVIEW_DEFAULT = 0,
		PREVIEW_LINE,
		PREVIEW_TRIGGER,

		PREVIEW_COUNT,
	};

	P2DEdit(camera::FbCamera* pCamera,
			const std::string& BasePanel = "p2dedit/p2dedit.ui",
			const std::string& EnterScript = "",
			const std::string& ExitScript = "");

	virtual ~P2DEdit();

	// overrride for custom behavior
	virtual void		CreateContainer();
	virtual void		InitWidgets();

	// overridable limits
	virtual int			MinCount() const { return 1; }
	virtual int			MaxCount() const { return 500; }
	virtual float		MinV() const { return -1.0f; }
	virtual float		MaxV() const { return 1.0f; }
	virtual float		MaxFreq() const { return 1000.0f; }
	virtual float		MaxLife() const { return 5.0f; }
	virtual float		MaxSize() const { return 0.1f; }
	virtual float		MinTriggerCount() const { return 1; }
	virtual float		MaxTriggerCount() const { return 50; }

	virtual bool		OnEnter();
	virtual bool		OnExit();
	virtual bool		PreRender();
	virtual	bool		PostRender();
	virtual	bool		Tick(float dt);
	virtual void		RefreshUI();

	// properties
	const PREVIEW_MODE&	GetPreviewMode() { return m_PreviewMode; }

	// static functions
	static void			Register(LuaPlus::LuaState* _pScript);
	static std::string	m_StateName;

	// luabind functions
	void				LoadParticle(const std::string& File);
	void				SaveParticle(const std::string& File);
	void				SetImage(const std::string& Sprite);
	void				SetGroup(int Group);
	int					AddGroup();
	int					DeleteGroup();
	void				SetMaxCount(float f);
	void				SetAdditive(bool b);
	void				SetLockRect(bool b);
	void				SetFuzzyBirth(float x, float y);
	void				SetSizeFromMin(float x, float y);
	void				SetSizeFromMax(float x, float y);
	void				SetSizeToMin(float x, float y);
	void				SetSizeToMax(float x, float y);
	void				SetLifespan(float x, float y);
	void				SetMinSpeed(float x, float y);
	void				SetMaxSpeed(float x, float y);
	void				SetStretchSpeed(float f);
	void				SetMinSpeedMag(float f);
	void				SetGenRate(float f);
	void				AddColor(float r, float g, float b, float a);
	void				ClearColors();
	void				UpdatePreviewPos();
	void				TogglePreviewMode();

protected:
	P2DEdit_Container*	m_pContainer;
	ui::UIWidget*		m_pPanel;

	PREVIEW_MODE		m_PreviewMode;
	math::Vec2			m_PreviewExtents[2];

	struct WIDGET_LIST {
		std::string		FileName;
		std::string		ImageName;
		std::string		PreviewPane;
		std::string		GroupList;
		std::string		MaxCount;
		std::string		Additive;
		std::string		LockRect;
		std::string		FuzzyBirthMin;
		std::string		FuzzyBirthMax;
		std::string		SizeFromMinX;
		std::string		SizeFromMinY;
		std::string		SizeFromMaxX;
		std::string		SizeFromMaxY;
		std::string		SizeToMinX;
		std::string		SizeToMinY;
		std::string		SizeToMaxX;
		std::string		SizeToMaxY;
		std::string		LifespanMin;
		std::string		LifespanMax;
		std::string		MinSpeedX;
		std::string		MinSpeedY;
		std::string		MaxSpeedX;
		std::string		MaxSpeedY;
		std::string		StretchSpeed;
		std::string		MinSpeedMag;
		std::string		GenRate;
		std::string		ColorR;
		std::string		ColorG;
		std::string		ColorB;
		std::string		ColorA;
		std::string		ColorPreview;
	};
	WIDGET_LIST			m_Widgets;

private:
	void				ClampV(math::Vec2& v);
	void				ExpandV(math::Vec2& v);
};

} //namespace part2d

#endif //_PART2D_EDITOR_H_
